{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "986e890e",
   "metadata": {},
   "source": [
    "# 第四讲 字符串（三）\n",
    "## 1. 删除前缀\n",
    "\n",
    "### 1.1 什么是前缀删除？\n",
    "\n",
    "#### (1) 前缀的定义\n",
    "\n",
    "**前缀（Prefix）** 是指字符串开头的固定部分，通常具有特定的格式或含义。\n",
    "\n",
    "#### (2) 常见的前缀示例\n",
    "\n",
    "- **URL前缀**：`https://`、`http://`、`ftp://`\n",
    "- **文件路径前缀**：`/home/user/`、`C:\\Users\\`\n",
    "- **协议前缀**：`tel:`、`mailto:`\n",
    "- **标识符前缀**：`ID_`、`USER_`、`TEMP_`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "407dde4b",
   "metadata": {},
   "source": [
    "## 2. removeprefix() 方法详解\n",
    "\n",
    "### 2.1 基本语法\n",
    "\n",
    "\n",
    "> 字符串.removeprefix(前缀)\n",
    "\n",
    "\n",
    "### 2.2 方法特点\n",
    "\n",
    "- **Python 3.9+** 新增方法\n",
    "- **返回新字符串**：不修改原字符串\n",
    "- **精确匹配**：只有完全匹配的前缀才会被删除\n",
    "- **安全操作**：如果前缀不存在，返回原字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "51ace342",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://nostarch.com\n",
      "nostarch.com\n"
     ]
    }
   ],
   "source": [
    "# 删除URL前缀\n",
    "nostarch_url = 'https://nostarch.com'\n",
    "nostarch_url.removeprefix('https://')\n",
    "\n",
    "print(nostarch_url)\n",
    "print(nostarch_url.removeprefix('https://'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4f995930",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原URL: https://www.example.com\n",
      "清理后: example.com\n",
      "------------------------------\n",
      "原URL: http://example.com\n",
      "清理后: example.com\n",
      "------------------------------\n",
      "原URL: www.example.com\n",
      "清理后: example.com\n",
      "------------------------------\n",
      "原URL: example.com\n",
      "清理后: example.com\n",
      "------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 处理用户输入的网址\n",
    "def clean_url(url):\n",
    "    \"\"\"清理URL，移除常见前缀\"\"\"\n",
    "    prefixes = ['https://', 'http://', 'www.']\n",
    "    clean_url = url\n",
    "    for prefix in prefixes:\n",
    "        clean_url = clean_url.removeprefix(prefix)\n",
    "    return clean_url\n",
    "\n",
    "# 测试\n",
    "urls = [\n",
    "    'https://www.example.com',\n",
    "    'http://example.com',\n",
    "    'www.example.com',\n",
    "    'example.com'\n",
    "]\n",
    "\n",
    "for url in urls:\n",
    "    print(f\"原URL: {url}\")\n",
    "    print(f\"清理后: {clean_url(url)}\")\n",
    "    print(\"-\" * 30)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0e72203",
   "metadata": {},
   "source": [
    "### 2.3 永久保存删除结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "85ca29e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nostarch.com\n"
     ]
    }
   ],
   "source": [
    "# 重新赋值给原变量\n",
    "nostarch_url = 'https://nostarch.com'\n",
    "nostarch_url = nostarch_url.removeprefix('https://')\n",
    "print(nostarch_url)  # 现在nostarch_url已经被更新"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e014299a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nostarch.com\n",
      "https://nostarch.com\n"
     ]
    }
   ],
   "source": [
    "# 赋值给新变量\n",
    "nostarch_url = 'https://nostarch.com'\n",
    "cleaned_url = nostarch_url.removeprefix('https://')\n",
    "print(cleaned_url)  # cleaned_url包含删除前缀后的结果\n",
    "print(nostarch_url)  # nostarch_url仍然保持原值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "64e8ddca",
   "metadata": {},
   "source": [
    "### 2.4 实际应用场景"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "54b679ff",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://www.python.org/downloads/ -> python.org\n",
      "http://github.com/user/repo -> github.com\n",
      "ftp://files.example.com/data.zip -> files.example.com\n",
      "www.stackoverflow.com/questions -> stackoverflow.com\n"
     ]
    }
   ],
   "source": [
    "# 1. URL处理\n",
    "class URLProcessor:\n",
    "    \"\"\"URL处理工具类\"\"\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def remove_protocol(url):\n",
    "        \"\"\"移除协议前缀\"\"\"\n",
    "        protocols = ['https://', 'http://', 'ftp://']\n",
    "        for protocol in protocols:\n",
    "            url = url.removeprefix(protocol)\n",
    "        return url\n",
    "    \n",
    "    @staticmethod\n",
    "    def remove_www(url):\n",
    "        \"\"\"移除www前缀\"\"\"\n",
    "        return url.removeprefix('www.')\n",
    "    \n",
    "    @staticmethod\n",
    "    def get_domain(url):\n",
    "        \"\"\"提取域名\"\"\"\n",
    "        # 移除协议\n",
    "        clean_url = URLProcessor.remove_protocol(url)\n",
    "        # 移除www\n",
    "        clean_url = URLProcessor.remove_www(clean_url)\n",
    "        # 移除路径部分\n",
    "        domain = clean_url.split('/')[0]\n",
    "        return domain\n",
    "\n",
    "# 使用示例\n",
    "urls = [\n",
    "    'https://www.python.org/downloads/',\n",
    "    'http://github.com/user/repo',\n",
    "    'ftp://files.example.com/data.zip',\n",
    "    'www.stackoverflow.com/questions'\n",
    "]\n",
    "\n",
    "for url in urls:\n",
    "    domain = URLProcessor.get_domain(url)\n",
    "    print(f\"{url} -> {domain}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d2b88097",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原路径: /home/user/projects/app.py\n",
      "相对路径: app.py\n",
      "--------------------------------------------------\n",
      "原路径: /home/user/projects/config/settings.py\n",
      "相对路径: config/settings.py\n",
      "--------------------------------------------------\n",
      "原路径: /home/user/projects/static/css/style.css\n",
      "相对路径: static/css/style.css\n",
      "--------------------------------------------------\n",
      "原路径: /home/user/projects/templates/index.html\n",
      "相对路径: templates/index.html\n",
      "--------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 2. 文件路径处理\n",
    "import os\n",
    "\n",
    "class PathProcessor:\n",
    "    \"\"\"路径处理工具类\"\"\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def remove_base_path(file_path, base_path):\n",
    "        \"\"\"移除基础路径前缀\"\"\"\n",
    "        # 确保路径格式一致\n",
    "        file_path = file_path.replace('\\\\', '/')\n",
    "        base_path = base_path.replace('\\\\', '/')\n",
    "        \n",
    "        # 确保基础路径以/结尾\n",
    "        if not base_path.endswith('/'):\n",
    "            base_path += '/'\n",
    "        \n",
    "        return file_path.removeprefix(base_path)\n",
    "    \n",
    "    @staticmethod\n",
    "    def get_relative_paths(file_list, base_dir):\n",
    "        \"\"\"获取相对路径列表\"\"\"\n",
    "        relative_paths = []\n",
    "        for file_path in file_list:\n",
    "            rel_path = PathProcessor.remove_base_path(file_path, base_dir)\n",
    "            relative_paths.append(rel_path)\n",
    "        return relative_paths\n",
    "\n",
    "# 使用示例\n",
    "base_directory = \"/home/user/projects/\"\n",
    "files = [\n",
    "    \"/home/user/projects/app.py\",\n",
    "    \"/home/user/projects/config/settings.py\",\n",
    "    \"/home/user/projects/static/css/style.css\",\n",
    "    \"/home/user/projects/templates/index.html\"\n",
    "]\n",
    "\n",
    "relative_files = PathProcessor.get_relative_paths(files, base_directory)\n",
    "for original, relative in zip(files, relative_files):\n",
    "    print(f\"原路径: {original}\")\n",
    "    print(f\"相对路径: {relative}\")\n",
    "    print(\"-\" * 50)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f9e1838c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "电话号码清理：\n",
      "+86-13812345678 -> 13812345678\n",
      "86 13987654321 -> 13987654321\n",
      "15612345678 -> 15612345678\n",
      "\n",
      "邮件主题清理：\n",
      "Re: 会议通知 -> 会议通知\n",
      "Fwd: 重要文件 -> 重要文件\n",
      "项目更新 -> 项目更新\n",
      "\n",
      "产品代码清理：\n",
      "PROD-12345 -> 12345\n",
      "SKU-ABC123 -> ABC123\n",
      "ITEM-XYZ789 -> XYZ789\n"
     ]
    }
   ],
   "source": [
    "# 3. 数据清理\n",
    "class DataCleaner:\n",
    "    \"\"\"数据清理工具\"\"\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def clean_phone_number(phone):\n",
    "        \"\"\"清理电话号码前缀\"\"\"\n",
    "        # 移除常见的电话号码前缀\n",
    "        prefixes = ['+86-', '+86 ', '86-', '86 ', '0086-', '0086 ']\n",
    "        clean_phone = phone\n",
    "        for prefix in prefixes:\n",
    "            clean_phone = clean_phone.removeprefix(prefix)\n",
    "        return clean_phone\n",
    "    \n",
    "    @staticmethod\n",
    "    def clean_email_subject(subject):\n",
    "        \"\"\"清理邮件主题前缀\"\"\"\n",
    "        prefixes = ['Re: ', 'RE: ', 'Fwd: ', 'FWD: ', 'Fw: ']\n",
    "        clean_subject = subject\n",
    "        for prefix in prefixes:\n",
    "            clean_subject = clean_subject.removeprefix(prefix)\n",
    "        return clean_subject\n",
    "    \n",
    "    @staticmethod\n",
    "    def clean_product_code(code):\n",
    "        \"\"\"清理产品代码前缀\"\"\"\n",
    "        prefixes = ['PROD-', 'SKU-', 'ITEM-']\n",
    "        clean_code = code\n",
    "        for prefix in prefixes:\n",
    "            clean_code = clean_code.removeprefix(prefix)\n",
    "        return clean_code\n",
    "\n",
    "# 使用示例\n",
    "test_data = {\n",
    "    'phones': ['+86-13812345678', '86 13987654321', '15612345678'],\n",
    "    'subjects': ['Re: 会议通知', 'Fwd: 重要文件', '项目更新'],\n",
    "    'products': ['PROD-12345', 'SKU-ABC123', 'ITEM-XYZ789']\n",
    "}\n",
    "\n",
    "print(\"电话号码清理：\")\n",
    "for phone in test_data['phones']:\n",
    "    clean = DataCleaner.clean_phone_number(phone)\n",
    "    print(f\"{phone} -> {clean}\")\n",
    "\n",
    "print(\"\\n邮件主题清理：\")\n",
    "for subject in test_data['subjects']:\n",
    "    clean = DataCleaner.clean_email_subject(subject)\n",
    "    print(f\"{subject} -> {clean}\")\n",
    "\n",
    "print(\"\\n产品代码清理：\")\n",
    "for code in test_data['products']:\n",
    "    clean = DataCleaner.clean_product_code(code)\n",
    "    print(f\"{code} -> {clean}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "09f31553",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "清理后的配置：\n",
      "database_url: postgresql://localhost:5432/mydb\n",
      "debug: True\n",
      "secret_key: your-secret-key\n",
      "port: 8000\n",
      "log_level: INFO\n"
     ]
    }
   ],
   "source": [
    "# 4. 配置文件处理\n",
    "class ConfigProcessor:\n",
    "    \"\"\"配置文件处理器\"\"\"\n",
    "    \n",
    "    def __init__(self, env_prefix=\"APP_\"):\n",
    "        self.env_prefix = env_prefix\n",
    "    \n",
    "    def clean_env_key(self, key):\n",
    "        \"\"\"移除环境变量前缀\"\"\"\n",
    "        return key.removeprefix(self.env_prefix)\n",
    "    \n",
    "    def process_env_vars(self, env_dict):\n",
    "        \"\"\"处理环境变量字典\"\"\"\n",
    "        cleaned_config = {}\n",
    "        for key, value in env_dict.items():\n",
    "            if key.startswith(self.env_prefix):\n",
    "                clean_key = self.clean_env_key(key)\n",
    "                cleaned_config[clean_key.lower()] = value\n",
    "        return cleaned_config\n",
    "\n",
    "# 使用示例\n",
    "env_variables = {\n",
    "    'APP_DATABASE_URL': 'postgresql://localhost:5432/mydb',\n",
    "    'APP_DEBUG': 'True',\n",
    "    'APP_SECRET_KEY': 'your-secret-key',\n",
    "    'APP_PORT': '8000',\n",
    "    'SYSTEM_PATH': '/usr/bin',  # 不是APP_前缀，会被忽略\n",
    "    'APP_LOG_LEVEL': 'INFO'\n",
    "}\n",
    "\n",
    "processor = ConfigProcessor(\"APP_\")\n",
    "config = processor.process_env_vars(env_variables)\n",
    "\n",
    "print(\"清理后的配置：\")\n",
    "for key, value in config.items():\n",
    "    print(f\"{key}: {value}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fad30179",
   "metadata": {},
   "source": [
    "### 2.5 高级用法和技巧"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "47176929",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DEBUG: 用户登录成功\n"
     ]
    }
   ],
   "source": [
    "# 1. 条件删除前缀\n",
    "def conditional_remove_prefix(text, prefix, condition=True):\n",
    "    \"\"\"根据条件删除前缀\"\"\"\n",
    "    if condition:\n",
    "        return text.removeprefix(prefix)\n",
    "    return text\n",
    "\n",
    "# 示例：只在开发环境下移除调试前缀\n",
    "DEBUG = True\n",
    "log_message = \"DEBUG: 用户登录成功\"\n",
    "clean_message = conditional_remove_prefix(log_message, \"DEBUG: \", not DEBUG)\n",
    "print(clean_message)  # 开发环境下输出: \"用户登录成功\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "36aef3b8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "file.txt\n"
     ]
    }
   ],
   "source": [
    "# 2. 多层前缀删除\n",
    "def remove_multiple_prefixes(text, prefixes):\n",
    "    \"\"\"删除多个前缀（按顺序）\"\"\"\n",
    "    result = text\n",
    "    for prefix in prefixes:\n",
    "        result = result.removeprefix(prefix)\n",
    "    return result\n",
    "\n",
    "# 示例：处理嵌套前缀\n",
    "nested_text = \"TEMP_BACKUP_file.txt\"\n",
    "prefixes = [\"TEMP_\", \"BACKUP_\"]\n",
    "clean_text = remove_multiple_prefixes(nested_text, prefixes)\n",
    "print(clean_text)  # 输出: \"file.txt\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6bde8b5f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原文本: https://www.example.com\n",
      "找到前缀: https://\n",
      "清理后: www.example.com\n"
     ]
    }
   ],
   "source": [
    "# 3. 智能前缀检测\n",
    "def smart_prefix_removal(text, possible_prefixes):\n",
    "    \"\"\"智能检测并删除可能的前缀\"\"\"\n",
    "    for prefix in possible_prefixes:\n",
    "        if text.startswith(prefix):\n",
    "            return text.removeprefix(prefix), prefix\n",
    "    return text, None\n",
    "\n",
    "# 示例\n",
    "text = \"https://www.example.com\"\n",
    "prefixes = [\"http://\", \"https://\", \"ftp://\"]\n",
    "clean_text, found_prefix = smart_prefix_removal(text, prefixes)\n",
    "print(f\"原文本: {text}\")\n",
    "print(f\"找到前缀: {found_prefix}\")\n",
    "print(f\"清理后: {clean_text}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "694db2d0",
   "metadata": {},
   "source": [
    "### 2.6 与其他字符串方法的组合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4fb6d3ac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'hello world'\n"
     ]
    }
   ],
   "source": [
    "# 1. 与strip()组合\n",
    "def clean_and_strip(text, prefix):\n",
    "    \"\"\"删除前缀并清理空白\"\"\"\n",
    "    return text.removeprefix(prefix).strip()\n",
    "\n",
    "# 示例\n",
    "messy_text = \"PREFIX:   hello world   \"\n",
    "clean_text = clean_and_strip(messy_text, \"PREFIX:\")\n",
    "print(f\"'{clean_text}'\") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a5e48ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 与lower()组合\n",
    "def normalize_identifier(identifier, prefix):\n",
    "    \"\"\"标准化标识符（删除前缀并转小写）\"\"\"\n",
    "    return identifier.removeprefix(prefix).lower()\n",
    "\n",
    "# 示例\n",
    "ids = [\"USER_12345\", \"USER_ADMIN\", \"USER_GUEST\"]\n",
    "clean_ids = [normalize_identifier(id, \"USER_\") for id in ids]\n",
    "print(clean_ids)  # 输出: ['12345', 'admin', 'guest']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e00e0a05",
   "metadata": {},
   "source": [
    "### 2.7 练习"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2eed5712",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://www.google.com -> google.com\n",
      "http://github.com -> github.com\n",
      "www.stackoverflow.com -> stackoverflow.com\n",
      "python.org -> python.org\n"
     ]
    }
   ],
   "source": [
    "# URL清理器\n",
    "def create_url_cleaner():\n",
    "    \"\"\"创建URL清理函数\"\"\"\n",
    "    def clean_url(url):\n",
    "        # 移除协议前缀\n",
    "        protocols = ['https://', 'http://']\n",
    "        for protocol in protocols:\n",
    "            url = url.removeprefix(protocol)\n",
    "        \n",
    "        # 移除www前缀\n",
    "        url = url.removeprefix('www.')\n",
    "        \n",
    "        return url\n",
    "    \n",
    "    return clean_url\n",
    "\n",
    "# 测试\n",
    "cleaner = create_url_cleaner()\n",
    "test_urls = [\n",
    "    'https://www.google.com',\n",
    "    'http://github.com',\n",
    "    'www.stackoverflow.com',\n",
    "    'python.org'\n",
    "]\n",
    "\n",
    "for url in test_urls:\n",
    "    print(f\"{url} -> {cleaner(url)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "fc2b9d6e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['config.txt', 'database.sql', 'script.py', 'normal.txt']\n"
     ]
    }
   ],
   "source": [
    "# 文件名处理器\n",
    "def process_backup_files(file_list):\n",
    "    \"\"\"处理备份文件列表，移除备份前缀\"\"\"\n",
    "    backup_prefixes = ['backup_', 'bak_', 'old_']\n",
    "    processed_files = []\n",
    "    \n",
    "    for filename in file_list:\n",
    "        clean_name = filename\n",
    "        for prefix in backup_prefixes:\n",
    "            clean_name = clean_name.removeprefix(prefix)\n",
    "        processed_files.append(clean_name)\n",
    "    \n",
    "    return processed_files\n",
    "\n",
    "# 测试\n",
    "files = ['backup_config.txt', 'bak_database.sql', 'old_script.py', 'normal.txt']\n",
    "clean_files = process_backup_files(files)\n",
    "print(clean_files)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "d85eba28",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "urls: ['python.org', 'github.com']\n",
      "subjects: ['会议通知', '重要文件']\n",
      "phones: ['13812345678', '13987654321']\n",
      "names: ['张三', '李四']\n"
     ]
    }
   ],
   "source": [
    "# 综合文本处理器\n",
    "class AdvancedTextProcessor:\n",
    "    \"\"\"高级文本处理器\"\"\"\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.url_prefixes = ['https://', 'http://', 'ftp://']\n",
    "        self.email_prefixes = ['Re: ', 'Fwd: ', 'RE: ', 'FWD: ']\n",
    "        self.phone_prefixes = ['+86-', '+86 ', '86-', '86 ']\n",
    "    \n",
    "    def process_url(self, url):\n",
    "        \"\"\"处理URL\"\"\"\n",
    "        clean_url = url.strip()\n",
    "        for prefix in self.url_prefixes:\n",
    "            clean_url = clean_url.removeprefix(prefix)\n",
    "        clean_url = clean_url.removeprefix('www.')\n",
    "        return clean_url\n",
    "    \n",
    "    def process_email_subject(self, subject):\n",
    "        \"\"\"处理邮件主题\"\"\"\n",
    "        clean_subject = subject.strip()\n",
    "        for prefix in self.email_prefixes:\n",
    "            clean_subject = clean_subject.removeprefix(prefix)\n",
    "        return clean_subject\n",
    "    \n",
    "    def process_phone(self, phone):\n",
    "        \"\"\"处理电话号码\"\"\"\n",
    "        clean_phone = phone.strip()\n",
    "        for prefix in self.phone_prefixes:\n",
    "            clean_phone = clean_phone.removeprefix(prefix)\n",
    "        return clean_phone\n",
    "    \n",
    "    def batch_process(self, data_dict):\n",
    "        \"\"\"批量处理数据\"\"\"\n",
    "        results = {}\n",
    "        for key, value in data_dict.items():\n",
    "            if key == 'urls':\n",
    "                results[key] = [self.process_url(url) for url in value]\n",
    "            elif key == 'subjects':\n",
    "                results[key] = [self.process_email_subject(subj) for subj in value]\n",
    "            elif key == 'phones':\n",
    "                results[key] = [self.process_phone(phone) for phone in value]\n",
    "            else:\n",
    "                results[key] = value\n",
    "        return results\n",
    "\n",
    "# 测试\n",
    "processor = AdvancedTextProcessor()\n",
    "test_data = {\n",
    "    'urls': ['https://www.python.org', 'http://github.com'],\n",
    "    'subjects': ['Re: 会议通知', 'Fwd: 重要文件'],\n",
    "    'phones': ['+86-13812345678', '86 13987654321'],\n",
    "    'names': ['张三', '李四']  # 不处理的数据\n",
    "}\n",
    "\n",
    "results = processor.batch_process(test_data)\n",
    "for key, value in results.items():\n",
    "    print(f\"{key}: {value}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c14bf8b8",
   "metadata": {},
   "source": [
    "## 3. 如何在使用字符串时避免语法错误\n",
    "\n",
    "### 3.1 什么是语法错误？\n",
    "#### (1) 语法错误的定义\n",
    "\n",
    "**语法错误（SyntaxError）** 是指程序包含非法的Python代码时产生的错误。这类错误会阻止程序运行，必须在执行前修复。\n",
    "\n",
    "#### (2) 语法错误的特点\n",
    "\n",
    "- **编译时错误**：在程序运行前就会被发现\n",
    "- **阻止执行**：程序无法启动\n",
    "- **位置明确**：通常会指出错误的具体位置\n",
    "- **必须修复**：不修复就无法运行程序\n",
    "\n",
    "### 3.2 字符串中的引号问题\n",
    "当在单引号字符串中使用撇号时，Python解释器会混淆：\n",
    "\n",
    "```python\n",
    "# 错误的写法 - 会导致语法错误\n",
    "message = 'One of Python's strengths is its diverse community.'\n",
    "```\n",
    "\n",
    "错误分析\n",
    "\n",
    "Python将上述代码解释为：\n",
    "\n",
    "1. `'One of Python'` - 第一个字符串\n",
    "2. `s strengths is its diverse community.'` - 剩余部分被视为Python代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5c98a648",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "One of Python's strengths is its diverse community.\n"
     ]
    }
   ],
   "source": [
    "# 使用双引号包围包含撇号的字符串\n",
    "message = \"One of Python's strengths is its diverse community.\"\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "7855cea5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "One of Python's strengths is its diverse community.\n"
     ]
    }
   ],
   "source": [
    "# 使用转义字符\n",
    "message = 'One of Python\\'s strengths is its diverse community.'\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "85e95169",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "One of Python's strengths is its diverse community.\n"
     ]
    }
   ],
   "source": [
    "# 使用三引号\n",
    "message = '''One of Python's strengths is its diverse community.'''\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c52588e0",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "unterminated string literal (detected at line 2) (4256615944.py, line 2)",
     "output_type": "error",
     "traceback": [
      "  \u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[31m    \u001b[39m\u001b[31mmessage = 'One of Python's strengths is its diverse community.'\u001b[39m\n                                                                  ^\n\u001b[31mSyntaxError\u001b[39m\u001b[31m:\u001b[39m unterminated string literal (detected at line 2)\n"
     ]
    }
   ],
   "source": [
    "# 这段代码会产生语法错误\n",
    "message = 'One of Python's strengths is its diverse community.'\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8120f27",
   "metadata": {},
   "source": [
    "#### 错误信息解读\n",
    "\n",
    "- **File \"apostrophe.py\", line 1**：错误发生在文件的第1行\n",
    "- **^符号**：指向错误位置（最后一个单引号后面）\n",
    "- **SyntaxError**：错误类型为语法错误\n",
    "- **unterminated string literal**：未终止的字符串字面量"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d15229aa",
   "metadata": {},
   "source": [
    "### 3.3 常见的字符串语法错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88c67df8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 引号不匹配\n",
    "# 开始和结束引号不匹配\n",
    "message = \"Hello world'\n",
    "name = 'Python\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2f4b5d9b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 正确写法\n",
    "message = \"Hello world\"\n",
    "name = 'Python'\n",
    "# 或者\n",
    "message = 'Hello world'\n",
    "name = \"Python\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a202cfef",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "unterminated string literal (detected at line 3) (3323931543.py, line 3)",
     "output_type": "error",
     "traceback": [
      "  \u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[6]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[31m    \u001b[39m\u001b[31mquote = 'He said \"I love Python's simplicity\"'\u001b[39m\n                                                ^\n\u001b[31mSyntaxError\u001b[39m\u001b[31m:\u001b[39m unterminated string literal (detected at line 3)\n"
     ]
    }
   ],
   "source": [
    "# 2. 嵌套引号问题\n",
    "# 嵌套相同类型的引号\n",
    "quote = 'He said \"I love Python's simplicity\"'  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "14318181",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 正确写法\n",
    "# 方案1：外层用双引号，内层用单引号\n",
    "quote = \"He said 'I love Python's simplicity'\"\n",
    "\n",
    "# 方案2：使用转义字符\n",
    "quote = 'He said \"I love Python\\'s simplicity\"'\n",
    "\n",
    "# 方案3：使用三引号\n",
    "quote = '''He said \"I love Python's simplicity\"'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8fba9bc2",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "unterminated string literal (detected at line 3) (3231827315.py, line 3)",
     "output_type": "error",
     "traceback": [
      "  \u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[9]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[31m    \u001b[39m\u001b[31mmessage = \"This is a very long message\u001b[39m\n              ^\n\u001b[31mSyntaxError\u001b[39m\u001b[31m:\u001b[39m unterminated string literal (detected at line 3)\n"
     ]
    }
   ],
   "source": [
    "# 3. 多行字符串错误\n",
    "# 试图在单引号或双引号中换行\n",
    "message = \"This is a very long message\n",
    "that spans multiple lines\"  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1ac7bdc0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 正确写法\n",
    "# 方案1：使用三引号\n",
    "message = \"\"\"This is a very long message\n",
    "that spans multiple lines\"\"\"\n",
    "\n",
    "# 方案2：使用字符串连接\n",
    "message = \"This is a very long message \" + \\\n",
    "          \"that spans multiple lines\"\n",
    "\n",
    "# 方案3：使用括号\n",
    "message = (\"This is a very long message \"\n",
    "           \"that spans multiple lines\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e229de2",
   "metadata": {},
   "source": [
    "### 3.4 实际应用场景"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "43836039",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 处理包含引号的文本\n",
    "class QuoteHandler:\n",
    "    \"\"\"处理包含引号的文本\"\"\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def safe_quote(text, quote_type='double'):\n",
    "        \"\"\"安全地为文本添加引号\"\"\"\n",
    "        if quote_type == 'double':\n",
    "            if '\"' in text:\n",
    "                return f\"'{text}'\"\n",
    "            else:\n",
    "                return f'\"{text}\"'\n",
    "        else:  # single\n",
    "            if \"'\" in text:\n",
    "                return f'\"{text}\"'\n",
    "            else:\n",
    "                return f\"'{text}'\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def extract_quotes(text):\n",
    "        \"\"\"提取文本中的引号内容\"\"\"\n",
    "        import re\n",
    "        # 匹配双引号内的内容\n",
    "        double_quotes = re.findall(r'\"([^\"]*)\"', text)\n",
    "        # 匹配单引号内的内容\n",
    "        single_quotes = re.findall(r\"'([^']*)'\", text)\n",
    "        return double_quotes, single_quotes\n",
    "\n",
    "# 使用示例\n",
    "handler = QuoteHandler()\n",
    "\n",
    "# 安全添加引号\n",
    "texts = [\n",
    "    \"Hello world\",\n",
    "    \"It's a beautiful day\",\n",
    "    'He said \"Hello\"',\n",
    "    \"She said 'Hi' and he replied \\\"Hello\\\"\"\n",
    "]\n",
    "\n",
    "for text in texts:\n",
    "    safe_text = handler.safe_quote(text)\n",
    "    print(f\"原文: {text}\")\n",
    "    print(f\"安全引号: {safe_text}\")\n",
    "    print(\"-\" * 40)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "21f42817",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "database_host: localhost\n",
      "database_port: 3306\n",
      "database_name: myapp\n",
      "database_user: admin\n",
      "database_password: it's a secret\n",
      "app_name: My Application\n",
      "debug: true\n"
     ]
    }
   ],
   "source": [
    "# 2. 配置文件处理\n",
    "class ConfigParser:\n",
    "    \"\"\"配置文件解析器\"\"\"\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.config = {}\n",
    "    \n",
    "    def parse_line(self, line):\n",
    "        \"\"\"解析配置行\"\"\"\n",
    "        line = line.strip()\n",
    "        if not line or line.startswith('#'):\n",
    "            return None, None\n",
    "        \n",
    "        if '=' in line:\n",
    "            key, value = line.split('=', 1)\n",
    "            key = key.strip()\n",
    "            value = value.strip()\n",
    "            \n",
    "            # 处理引号包围的值\n",
    "            value = self.process_quoted_value(value)\n",
    "            return key, value\n",
    "        \n",
    "        return None, None\n",
    "    \n",
    "    def process_quoted_value(self, value):\n",
    "        \"\"\"处理被引号包围的值\"\"\"\n",
    "        # 移除外层引号\n",
    "        if (value.startswith('\"') and value.endswith('\"')) or \\\n",
    "           (value.startswith(\"'\") and value.endswith(\"'\")):\n",
    "            return value[1:-1]\n",
    "        return value\n",
    "    \n",
    "    def load_config(self, config_text):\n",
    "        \"\"\"加载配置文本\"\"\"\n",
    "        for line in config_text.split('\\n'):\n",
    "            key, value = self.parse_line(line)\n",
    "            if key and value is not None:\n",
    "                self.config[key] = value\n",
    "        return self.config\n",
    "\n",
    "# 使用示例\n",
    "config_text = '''\n",
    "# 数据库配置\n",
    "database_host = \"localhost\"\n",
    "database_port = 3306\n",
    "database_name = 'myapp'\n",
    "database_user = \"admin\"\n",
    "database_password = \"it's a secret\"\n",
    "\n",
    "# 应用配置\n",
    "app_name = \"My Application\"\n",
    "debug = true\n",
    "'''\n",
    "\n",
    "parser = ConfigParser()\n",
    "config = parser.load_config(config_text)\n",
    "for key, value in config.items():\n",
    "    print(f\"{key}: {value}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f1dd9256",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "生成的SQL查询:\n",
      "SELECT * FROM users WHERE name = 'O''Connor' AND city = 'New York' AND age = 25\n"
     ]
    }
   ],
   "source": [
    "# 3. 动态SQL查询构建\n",
    "class SQLBuilder:\n",
    "    \"\"\"SQL查询构建器\"\"\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def escape_string(value):\n",
    "        \"\"\"转义字符串中的特殊字符\"\"\"\n",
    "        if isinstance(value, str):\n",
    "            # 转义单引号\n",
    "            return value.replace(\"'\", \"''\")\n",
    "        return str(value)\n",
    "    \n",
    "    @staticmethod\n",
    "    def build_where_clause(conditions):\n",
    "        \"\"\"构建WHERE子句\"\"\"\n",
    "        clauses = []\n",
    "        for column, value in conditions.items():\n",
    "            if isinstance(value, str):\n",
    "                escaped_value = SQLBuilder.escape_string(value)\n",
    "                clauses.append(f\"{column} = '{escaped_value}'\")\n",
    "            else:\n",
    "                clauses.append(f\"{column} = {value}\")\n",
    "        \n",
    "        return \" AND \".join(clauses)\n",
    "    \n",
    "    @staticmethod\n",
    "    def build_select(table, columns=\"*\", conditions=None):\n",
    "        \"\"\"构建SELECT查询\"\"\"\n",
    "        query = f\"SELECT {columns} FROM {table}\"\n",
    "        \n",
    "        if conditions:\n",
    "            where_clause = SQLBuilder.build_where_clause(conditions)\n",
    "            query += f\" WHERE {where_clause}\"\n",
    "        \n",
    "        return query\n",
    "\n",
    "# 使用示例\n",
    "builder = SQLBuilder()\n",
    "\n",
    "# 包含撇号的数据\n",
    "conditions = {\n",
    "    'name': \"O'Connor\",\n",
    "    'city': \"New York\",\n",
    "    'age': 25\n",
    "}\n",
    "\n",
    "query = builder.build_select('users', conditions=conditions)\n",
    "print(\"生成的SQL查询:\")\n",
    "print(query)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "493e78a6",
   "metadata": {},
   "source": [
    "### 3.4 调试和预防策略"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3fe474d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用语法高亮\n",
    "# 好的编辑器会用不同颜色显示：\n",
    "message = \"This is a string\"  # 字符串颜色\n",
    "print(message)                # 代码颜色\n",
    "\n",
    "# 错误的引号会导致颜色异常：\n",
    "message = 'This is a string\"  # 颜色会异常\n",
    "print(message)                "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f91e316",
   "metadata": {},
   "source": [
    "### 3.5 最佳实践"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c951e4ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 引号使用规范\n",
    "# 1. 优先使用双引号作为外层引号\n",
    "message = \"Hello, world!\"\n",
    "\n",
    "# 2. 当字符串包含双引号时，使用单引号\n",
    "html_tag = '<div class=\"container\">Content</div>'\n",
    "\n",
    "# 3. 当字符串包含撇号时，使用双引号\n",
    "contraction = \"It's a beautiful day\"\n",
    "\n",
    "# 4. 复杂情况使用三引号\n",
    "complex_string = \"\"\"\n",
    "This string contains both \"double quotes\" and 'single quotes'.\n",
    "It can also span multiple lines.\n",
    "\"\"\"\n",
    "\n",
    "# 5. 一致性原则：在同一个项目中保持一致的风格"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "2d2ce810",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, John. Welcome to Python's world!\n"
     ]
    }
   ],
   "source": [
    "# 使用字符串模板避免复杂的引号嵌套\n",
    "from string import Template\n",
    "\n",
    "# 传统方法（容易出错）\n",
    "name = \"John\"\n",
    "message = 'Hello, ' + name + '. Welcome to Python\\'s world!'\n",
    "\n",
    "# 使用f-string（推荐）\n",
    "message = f\"Hello, {name}. Welcome to Python's world!\"\n",
    "\n",
    "# 使用Template类\n",
    "template = Template(\"Hello, $name. Welcome to Python's world!\")\n",
    "message = template.substitute(name=name)\n",
    "\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "8de6da2a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入: Hello world\n",
      "结果: Processed: Hello world\n",
      "------------------------------\n",
      "输入: It's working\n",
      "结果: Processed: It's working\n",
      "------------------------------\n",
      "输入: He said \"Hi\"\n",
      "结果: Processed: He said \"Hi\"\n",
      "------------------------------\n",
      "输入: Unclosed quote'\n",
      "结果: Processed: Unclosed quote'\n",
      "------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 错误处理\n",
    "def safe_string_operation(text, operation):\n",
    "    \"\"\"安全的字符串操作\"\"\"\n",
    "    try:\n",
    "        if operation == 'eval':\n",
    "            # 危险操作，仅用于演示\n",
    "            return eval(f'\"{text}\"')\n",
    "        elif operation == 'format':\n",
    "            return f\"Processed: {text}\"\n",
    "        else:\n",
    "            return text\n",
    "    except SyntaxError as e:\n",
    "        print(f\"语法错误: {e}\")\n",
    "        return None\n",
    "    except Exception as e:\n",
    "        print(f\"其他错误: {e}\")\n",
    "        return None\n",
    "\n",
    "# 测试\n",
    "test_strings = [\n",
    "    \"Hello world\",\n",
    "    \"It's working\",\n",
    "    'He said \"Hi\"',\n",
    "    \"Unclosed quote'\",  # 这会在某些操作中出错\n",
    "]\n",
    "\n",
    "for test_str in test_strings:\n",
    "    result = safe_string_operation(test_str, 'format')\n",
    "    print(f\"输入: {test_str}\")\n",
    "    print(f\"结果: {result}\")\n",
    "    print(\"-\" * 30)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d132df6f",
   "metadata": {},
   "source": [
    "### 3.5 练习"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db6e77c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 引号修复练习：修复以下代码中的语法错误\n",
    "def fix_syntax_errors():\n",
    "    # 错误1\n",
    "    message1 = 'It's a wonderful day'  # 需要修复\n",
    "    \n",
    "    # 错误2\n",
    "    message2 = \"He said \"Hello\" to me\"  # 需要修复\n",
    "    \n",
    "    # 错误3\n",
    "    message3 = 'The file is located at C:\\Users\\John's Documents'  # 需要修复\n",
    "    \n",
    "    return message1, message2, message3\n",
    "\n",
    "# 正确答案\n",
    "def fix_syntax_errors_correct():\n",
    "    message1 = \"It's a wonderful day\"\n",
    "    message2 = 'He said \"Hello\" to me'\n",
    "    message3 = \"The file is located at C:\\\\Users\\\\John's Documents\"\n",
    "    \n",
    "    return message1, message2, message3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "378eb37d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 字符串验证器\n",
    "def validate_string_syntax(code_string):\n",
    "    \"\"\"验证字符串语法是否正确\"\"\"\n",
    "    try:\n",
    "        # 尝试编译代码\n",
    "        compile(code_string, '<string>', 'eval')\n",
    "        return True, \"语法正确\"\n",
    "    except SyntaxError as e:\n",
    "        return False, f\"语法错误: {e}\"\n",
    "\n",
    "# 测试用例\n",
    "test_cases = [\n",
    "    '\"Hello world\"',\n",
    "    \"'It's working'\",  # 错误\n",
    "    '\"He said \\\\\"Hi\\\\\"\"',\n",
    "    \"'Valid string'\",\n",
    "]\n",
    "\n",
    "for case in test_cases:\n",
    "    is_valid, message = validate_string_syntax(case)\n",
    "    print(f\"代码: {case}\")\n",
    "    print(f\"结果: {message}\")\n",
    "    print(\"-\" * 30)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "68a052f0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "字符串: Hello world\n",
      "有效: True\n",
      "--------------------------------------------------\n",
      "字符串: 'It's a test'\n",
      "有效: False\n",
      "问题: 单引号数量不平衡\n",
      "建议: 考虑使用双引号包围包含撇号的字符串\n",
      "--------------------------------------------------\n",
      "字符串: \"He said \"Hi\"\"\n",
      "有效: True\n",
      "建议: 考虑使用单引号包围包含双引号的字符串\n",
      "--------------------------------------------------\n",
      "字符串: \"\"\"Complex string with \"quotes\" and 'apostrophes'\"\"\"\n",
      "有效: True\n",
      "建议: 考虑使用单引号包围包含双引号的字符串\n",
      "--------------------------------------------------\n",
      "字符串: Unbalanced quote'\n",
      "有效: False\n",
      "问题: 单引号数量不平衡\n",
      "--------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 进阶练习\n",
    "class StringSyntaxChecker:\n",
    "    \"\"\"字符串语法检查器\"\"\"\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.errors = []\n",
    "    \n",
    "    def check_quote_balance(self, text):\n",
    "        \"\"\"检查引号是否平衡\"\"\"\n",
    "        single_quotes = text.count(\"'\")\n",
    "        double_quotes = text.count('\"')\n",
    "        \n",
    "        issues = []\n",
    "        if single_quotes % 2 != 0:\n",
    "            issues.append(\"单引号数量不平衡\")\n",
    "        if double_quotes % 2 != 0:\n",
    "            issues.append(\"双引号数量不平衡\")\n",
    "        \n",
    "        return issues\n",
    "    \n",
    "    def suggest_fixes(self, text):\n",
    "        \"\"\"建议修复方案\"\"\"\n",
    "        suggestions = []\n",
    "        \n",
    "        # 检查是否包含撇号\n",
    "        if \"'\" in text and text.count(\"'\") > 2:\n",
    "            suggestions.append(\"考虑使用双引号包围包含撇号的字符串\")\n",
    "        \n",
    "        # 检查是否包含双引号\n",
    "        if '\"' in text and text.count('\"') > 2:\n",
    "            suggestions.append(\"考虑使用单引号包围包含双引号的字符串\")\n",
    "        \n",
    "        # 检查是否需要转义\n",
    "        if \"\\\\'\" in text or '\\\\\"' in text:\n",
    "            suggestions.append(\"考虑使用三引号避免转义\")\n",
    "        \n",
    "        return suggestions\n",
    "    \n",
    "    def analyze_string(self, text):\n",
    "        \"\"\"分析字符串并提供建议\"\"\"\n",
    "        issues = self.check_quote_balance(text)\n",
    "        suggestions = self.suggest_fixes(text)\n",
    "        \n",
    "        return {\n",
    "            'text': text,\n",
    "            'issues': issues,\n",
    "            'suggestions': suggestions,\n",
    "            'is_valid': len(issues) == 0\n",
    "        }\n",
    "\n",
    "# 测试\n",
    "checker = StringSyntaxChecker()\n",
    "test_strings = [\n",
    "    \"Hello world\",\n",
    "    \"'It's a test'\",\n",
    "    '\"He said \"Hi\"\"',\n",
    "    '\"\"\"Complex string with \"quotes\" and \\'apostrophes\\'\"\"\"',\n",
    "    \"Unbalanced quote'\"\n",
    "]\n",
    "\n",
    "for test_str in test_strings:\n",
    "    analysis = checker.analyze_string(test_str)\n",
    "    print(f\"字符串: {analysis['text']}\")\n",
    "    print(f\"有效: {analysis['is_valid']}\")\n",
    "    if analysis['issues']:\n",
    "        print(f\"问题: {', '.join(analysis['issues'])}\")\n",
    "    if analysis['suggestions']:\n",
    "        print(f\"建议: {', '.join(analysis['suggestions'])}\")\n",
    "    print(\"-\" * 50)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
